package cz.data.domain.elasticsearch.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cz.data.common.support.db.DbProperty;
import cz.data.common.support.db.driver.DataOperation;
import cz.data.common.support.db.manage.DbManage;
import cz.data.common.support.db.manage.DbManageFactory;
import cz.data.common.support.db.manage.DbManageRegistry;
import cz.data.common.utils.ThrowableUtil;
import cz.data.domain.metadata.model.MetadataUtil;
import cz.data.domain.metadata.model.entity.MetadataSourceEntity;
import cz.data.domain.metadata.rpc.MetadataFeign;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;

@Component
public class ElasticsearchOperationService {

    @Resource
    MetadataFeign metadataFeign;

    public JSONObject getDataById(DataOperation operation) {
        MetadataSourceEntity source = metadataFeign.getMetadataSourceById(operation.getSource());
        DbProperty property = MetadataUtil.dbProperty(source);
        DbManageFactory factory = DbManageRegistry.factory(property.getDbTypeEnum());
        DbManage dbManage = null;
        try {
            dbManage = factory.factory(property);
            return dbManage.getDataById(operation.getTable(), operation.getData());
        } finally {
            if (Objects.nonNull(dbManage)) {
                ThrowableUtil.throwable(dbManage::close);
            }
        }
    }

    public IPage<JSONObject> getPageData(DataOperation operation) {
        MetadataSourceEntity source = metadataFeign.getMetadataSourceById(operation.getSource());
        DbProperty property = MetadataUtil.dbProperty(source);
        DbManageFactory factory = DbManageRegistry.factory(property.getDbTypeEnum());
        DbManage dbManage = null;
        try {
            dbManage = factory.factory(property);
            Page<JSONObject> page = new Page<>(operation.getPageNum(), operation.getPageSize());
            return dbManage.getPageData(operation.getTable(), operation.getFields(),
                    operation.getConditions(), page);
        } finally {
            if (Objects.nonNull(dbManage)) {
                ThrowableUtil.throwable(dbManage::close);
            }
        }
    }

    public boolean insertData(DataOperation operation) {
        MetadataSourceEntity source = metadataFeign.getMetadataSourceById(operation.getSource());
        DbProperty property = MetadataUtil.dbProperty(source);
        DbManageFactory factory = DbManageRegistry.factory(property.getDbTypeEnum());
        DbManage dbManage = null;
        try {
            dbManage = factory.factory(property);
            return dbManage.insertData(operation.getTable(), operation.getData());
        } finally {
            if (Objects.nonNull(dbManage)) {
                ThrowableUtil.throwable(dbManage::close);
            }
        }
    }

    public boolean updateData(DataOperation operation) {
        MetadataSourceEntity source = metadataFeign.getMetadataSourceById(operation.getSource());
        DbProperty property = MetadataUtil.dbProperty(source);
        DbManageFactory factory = DbManageRegistry.factory(property.getDbTypeEnum());
        DbManage dbManage = null;
        try {
            dbManage = factory.factory(property);
            return dbManage.updateData(operation.getTable(), operation.getData());
        } finally {
            if (Objects.nonNull(dbManage)) {
                ThrowableUtil.throwable(dbManage::close);
            }
        }
    }

    public boolean removeData(DataOperation operation) {
        MetadataSourceEntity source = metadataFeign.getMetadataSourceById(operation.getSource());
        DbProperty property = MetadataUtil.dbProperty(source);
        DbManageFactory factory = DbManageRegistry.factory(property.getDbTypeEnum());
        DbManage dbManage = null;
        try {
            dbManage = factory.factory(property);
            return dbManage.removeData(operation.getTable(), operation.getData());
        } finally {
            if (Objects.nonNull(dbManage)) {
                ThrowableUtil.throwable(dbManage::close);
            }
        }
    }
}
